home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / COM / ProTERM Mac1.2a.sit / ProTERM Mac1.2a / Macros / AutoTime 1201 next >
Text File  |  1996-07-24  |  10KB  |  261 lines

  1. //
  2. // AutoTime Macro 1.2
  3. //
  4. // Greg Schaefer, 18-Mar-96
  5. //
  6.  
  7. /*
  8. This is an example to help demonstrate how to write DIRC macros. This macro automatically sets your Macintosh clock from a dialup time server.
  9.  
  10. This macro uses either the NIST (Boulder, CO) or Naval Observatory (Washington, DC) time server to determine the correct date and time for your Macintosh. In order to operate correctly, the 'map' control panel must have been used at some point to specify the location of your Macintosh. In addition, you must indicate whether you are on daylight savings time each time the macro is run.
  11. */
  12.  
  13. FUNC main()
  14. {
  15.  INT win,fd,x,y,z;
  16.  STR utc,dst,srv,s;
  17.  STR format,click,phone;
  18.  STR pref = ".PREF:%AutoTime Prefs";
  19.  
  20. // keep "macro running" window from being displayed
  21.  WIN_RUNNING(0);
  22.  
  23. // constants for summary template
  24.  STR togdst = "Using Daylight Savings Time";
  25.  STR rad303 = "Institute of Standards (Boulder, CO)";
  26.  STR rad202 = "Naval Observatory (Washinton, DC)";
  27.  
  28. // actual summary template
  29.  STR intro = D_NEW(0,0,240,350,0,"AutoTime Setup")+
  30.   D_FORM("WT+0 WL+0",40,20,"Current Timezone:")+
  31.   D_DIVIDER("PB+5 WL-50",1,500,0)+
  32.   D_TEXT("PB+5 WL+0","Select Time Server")+
  33.   D_RADIO("PB+0 WL+0",1,rad303)+
  34.   D_RADIO("PB+0 WL+0",1,rad202)+
  35.   D_DIVIDER("PB+5 WL-50",1,500,0)+
  36.   D_TOGGLE("PB+5 WL+0",togdst)+
  37.   D_DIVIDER("PB+7 WL-50",1,500,0)+
  38.   D_TEXT("PB+5 WL+0",
  39.    "WARNING: This macro makes a long-distance^m"+
  40.    "phone call in order to get the correct time^m"+
  41.    "and reset your Macintosh system clock."
  42.   )+
  43.   D_DIVIDER("PB+10 WL-50",1,500,0)+
  44.   D_DEFAULT("WB-0 WL+0","Start")+
  45.   D_BUTTON("PY+0 PR+15","Cancel");
  46.  
  47. // get the current utc offset
  48.  utc = GET_UTC();
  49.  IF (utc == "") { END }
  50.  
  51. // load the autotime prefs
  52.  dst = srv = "";
  53.  fd = F_OPEN(pref,"RO");
  54.  IF (fd > 0) {
  55.   IO_SCANF(fd,"%s^m",s);
  56.   IF (s == utc) { IO_SCANF(fd,"%s^m%s^m",dst,srv) }
  57.   F_CLOSE(fd);
  58.  }
  59.  
  60. // set default daylight savings value if needed
  61.  IF (dst == "") {
  62.   x = TIME_TO(0,1);
  63.   dst = { IF ((x < 4) || (x > 10)) { "1" } ELSE { "0" } }
  64.  }
  65.  
  66. // set default time server if needed
  67.  IF (srv == "") {
  68.   srv = { IF (utc > "UTC-6") { rad303 } ELSE { rad202 } }
  69.  }
  70.  
  71. // display the summary window
  72.  win = D_OPEN(intro);
  73.  D_SET(win,"Current Timezone:",utc);
  74.  D_SET(win,srv,"1");
  75.  D_SET(win,togdst,dst);
  76.  click = D_EVENT(win,0,"B");
  77.  dst = D_GET(win,togdst);
  78.  IF (D_GET(win,rad202) == "1") { srv = rad202; phone = "(202) 653-0351" }
  79.  IF (D_GET(win,rad303) == "1") { srv = rad303; phone = "(303) 494-4774" }
  80.  D_CLOSE(win);
  81.  IF (click != "Start") { END }
  82.  
  83. // save pref info back for later
  84.  F_CREATE(pref);
  85.  fd = F_OPEN(pref,"RW");
  86.  IO_PRINTF(fd,"%s^m%s^m%s^m",utc,dst,srv);
  87.  F_CLOSE(fd);
  88.  
  89. // connect to the time server
  90.  win = GET_CONN(phone);
  91.  IF (win == 0) { END } 
  92.  
  93. // calculate time change
  94.  x = GET_DELTA(&y,&z,(dst == "1"));
  95.  
  96. // disconnect from the time server
  97.  GET_HANG(win);
  98.  
  99. // advise user of time change & adjust
  100.  IF ((y == 0) && (z > -2) && (z < 2)) {
  101.   format = "Your clock is accurate within 1 second.^m"+
  102.            "No adjustment is needed.";
  103.   WIN_NOTE(4,format);
  104.  } ELSE IF (y == 0) {
  105.   format = "Your clock is off by %d seconds.^m"+
  106.            "Go ahead and correct it?";
  107.   IF (WIN_NOTE(5, STR_FORMAT(format,z)) == 1) {
  108.    TIME(-1,TIME(0)-z);
  109.   }
  110.  } ELSE {
  111.   format = "Your clock is off by %d days and %d secs.^m"+
  112.            "Go ahead and correct it?";
  113.   IF (WIN_NOTE(5, STR_FORMAT(format,y,z)) == 1) {
  114.    TIME(-1,TIME(0)-(y*86400)-z);
  115.   }
  116.  }
  117.  
  118. // show the current time
  119. str format;
  120.  format = "It is currently %*2D %*1T.";
  121.  WIN_NOTE(4,STR_FORMAT(format,0,0));
  122.  RETURN;
  123. }
  124.  
  125. // get the current utc offset
  126. FUNC GET_UTC()
  127. {
  128.  INT tz = (TIME(0) - TIME(1)) / 3600;
  129.  
  130.  IF (tz == 0) {
  131.   format = "You must use the 'Map' control panel to set^m"+
  132.            "the location and timezone of your Macintosh^m"+
  133.            "in order for this macro to operate.";
  134.   WIN_NOTE(4,format);
  135.   RETURN("");
  136.  }
  137.  
  138.  IF ((tz < -9) || (tz > -4)) {
  139.   format = "Sorry, the AutoTime macro only operates within^m"+
  140.            "North America (timezones UTC-5 to UTC-9)";
  141.   WIN_NOTE(4,format);
  142.   RETURN("");
  143.  }
  144.  
  145.  RETURN(STR_FORMAT("UTC%d",tz));
  146. }
  147.  
  148. // try and connect to time server
  149. FUNC GET_CONN(STR phone)
  150. {
  151.  INT win,term;
  152.  
  153.  win = UI_NUM("wind",0,UI_CMD("cmd=host"));
  154.  D_SET(win,"Name","Time Server");
  155.  D_SET(win,"Phone Number:",phone);
  156.  D_SET(win,"Speed","9600 BPS");
  157.  term = UI_NUM("term",0,UI_CMD('
  158.   cmd=connect wind=%d count=1 #sync
  159.   {**** cmd=msg wind=%d msg=CLOS}
  160.  ',win,win));
  161.  IF (term == 0) { RETURN(0) }
  162.  IO_INPCHAN(#TermChan,NUM_LONG(SES_GET(term,"ses")));
  163.  IO_OUTCHAN(#TermChan,NUM_LONG(SES_GET(term,"ses")));
  164.  RETURN(term);
  165. }
  166.  
  167.  
  168. // try and disconnect from server
  169. FUNC GET_HANG(INT win)
  170. {
  171.  WT(0);
  172.  UI_CMD('
  173.   {onln cmd=sess ptr=%d}
  174.   cmd=online sess=.onln.sess opt=disc +status
  175.   {**** cmd=msg wind=%d msg=CLOS}
  176.  ',win,win);
  177.  RETURN(0);
  178. }
  179.  
  180.  
  181. /*
  182. Use the output of the time server to set the Macintosh clock to the current time. Connecting to the time server provides a continuous output of time records. The two different time servers return records in different formats.
  183.  
  184. NIST:
  185. 49712 94-12-26 21:58:06 00 0 +.4 045.0 UTC(NIST) *
  186. 49712 94-12-26 21:58:07 00 0 +.4 045.0 UTC(NIST) *
  187. 49712 94-12-26 21:58:08 00 0 +.4 045.0 UTC(NIST) *
  188.  
  189. Naval Observatory:
  190. 49715 363 150019 UTC
  191. *
  192. 49715 363 150020 UTC
  193. *
  194. 49715 363 150021 UTC
  195. *
  196. */
  197. FUNC GET_DELTA(INT julian, INT offset, INT dst)
  198. {
  199.  INT window, target;
  200.  STR format, old_time, new_time;
  201.  
  202. /*
  203. Wait for the time server to start sending data. Look for UTC because it appears in the data. Then wait for a couple seconds to process any data which may have been buffered by the modem during the initial connection.
  204. */
  205.  WT("UTC");
  206.  WT(200);
  207.  
  208. /*
  209. Wait for two lines of input with identical lengths. This is an easy way to "get in sync" with the time server and get a complete line of time data.
  210. */
  211.  new_time = "";
  212.  DO {
  213.   old_time = new_time;
  214.   new_time = IN("^m");
  215.   IF (STR_LEN(new_time) < 5) { new_time = IN("^m"); }
  216.  } WHILE (STR_LEN(old_time) != STR_LEN(new_time));
  217.  
  218. /*
  219. Because the time server may send linefeeds and other non-data at the 
  220. start/end of each line, it is important to make sure the beginning of the line contains normal data. The line should start with a digit.
  221. */
  222.  WHILE (STR_LEFT(new_time, 1) < "0") {
  223.   new_time = STR_MID(new_time, 1, 80);
  224.  }
  225.  
  226. /*
  227. With the date/time field read, it is now possible to compute the offset between the Macintosh date and the real date. The Macintosh date is maintained as the number of elapsed seconds from Jan 1, 1904. The time server returns the date in modified julian day format. This means that date is expressed as the number of elapsed days from Nov 17, 1858 (actually it is really the number of elapsed days from Jan 1, 4713 B.C. mod 100000, but it is easier to think of it as the former). Converting from a Macintosh date to a julian date is really simple since all you need to do is convert from seconds to days (86400 seconds in a day). The "problem" is that the number which represents the Macintosh date (for any date past approx 1970) is larger than DIRC's largest positive integer. If you try and divide such a number, you get an invalid result. This can be avoided by subtracting 2398377600 (the number of elapsed seconds from Jan 1, 1904 to Jan 1, 1980) and making up the difference once the value is in julian format. Once converted to julian format, the offset between the Macintosh date and the time server date is determined which can later be used to "correct" the Macintosh clock.
  228. */
  229.  julian = ((TIME(1) - (dst*3600) - 2398377600) / 86400) + 44239;
  230.  julian = julian - NUM_STR(STR_LEFT(new_time, 5));
  231.  
  232. /*
  233. The "trick" to getting a decent time estimate is to use the current server time to compute a "target" time. The "target" time is the time at which the macro will determine the offset between the Macintosh clock and the server clock. Once the offset between the two clocks is known, the rest of the macro is no longer "time critical". The target time is set 3 seconds later than the current time. This gives sufficient time for the macro to complete its computations and accurately synchronize the determination of the offset.
  234.  
  235. The NIST and Naval Observatory time servers return the time in different formats. Therefore, there are two different routine to extract the time depending on which server is being used. It is possible to determine the server type by looking at the length of the time record returned by the server. The NIST server returns more information (a larger record) than the Naval server.
  236. */
  237.  IF (STR_LEN(new_time) > 25) {
  238.   target = NUM_STR(STR_MID(new_time, 15, 2)) * 3600 +
  239.    NUM_STR(STR_MID(new_time, 18, 2)) * 60 +
  240.    NUM_STR(STR_MID(new_time, 21, 2));
  241.   format = ":%02d ";
  242.  } ELSE {
  243.   target = NUM_STR(STR_MID(new_time, 10, 2)) * 3600 +
  244.    NUM_STR(STR_MID(new_time, 12, 2)) * 60 +
  245.    NUM_STR(STR_MID(new_time, 14, 2));
  246.   format = "%02d UTC";
  247.  }
  248.   target = (target + 3) % 86400;
  249.   WT(STR_FORMAT(format,target % 60));
  250.  
  251. /*
  252. The target time has now arrived (or at least is very close-- usually within 1 second which is good enough). Now figure out the offset by subtracting the server time from the Macintosh time. The 2147472000 is needed because the Macintosh time is expressed in elapsed seconds from January 1, 1904. This particular value is larger than the largest positive DIRC integer. In order to prevent an overflow, subtract 2398377600 from the time to turn it into a valid DIRC positive value. This works because the result is taken mod 86400 so as to get the offset relative to the current day. The resulting offset is in the range 0-86399. Values greater than 86400/2 are assumed to be negative and are changed to real negative values.
  253. */
  254.  offset = (TIME(1) - (dst*3600) - 2398377600 - target) % 86400;
  255.  IF (offset > 43200) { offset = offset - 86400; }
  256.  
  257.  RETURN(1);
  258. }
  259.  
  260.  
  261.